/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * CustomDeckPanel.java
 *
 * Created on 02/08/2011, 16:05:13
 */
package fallen.deck.front_end.jCustomTabbed;

import fallen.deck.Drecker;
import fallen.deck.entity.*;
import fallen.deck.front_end.customCardPanel.iCard;
import fallen.deck.hibernate.Queries;
import java.awt.Color;
import java.awt.event.ItemEvent;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;

/**
 *
 * @author Carlos S. Moreno <CarlosS.Moreno@gmail.com>
 */
public class CustomDeckPanel extends javax.swing.JPanel {

    private Deck deck;
    private DeckMetadata metadata;
    private iCard cardDetail;
    private Supertype unlimit = Queries.getSupertype("Ilimitado");
    protected CustomTableModel tableModel;

    /** Creates new form CustomDeckPanel */
    public CustomDeckPanel(Deck deck) {
        initComponents();
        this.deck = deck;
        this.metadata = new DeckMetadata();
        cardDetail = new iCard(250, deck.getDemon());
        pnlCardDetail.add(cardDetail);
        pnlCardDetail.repaint();
        prepareRenders();
        setReorderingListeners();
        setColumnsWidth();
        prepareTableListeners();
        if (deck.getCards().size() > 0) {
            loadDeckCardsOnTable();
        }

        lblAlert.setVisible(false);
    }

    private void setReorderingListeners() {
        tableModel = new CustomTableModel();
        JTableHeader header = jTable.getTableHeader();
        header.setUpdateTableInRealTime(true);
        header.addMouseListener(tableModel.new ColumnListener(jTable));
        header.setReorderingAllowed(true);
    }

    private void prepareTableListeners() {
        SelectionListener listener = new SelectionListener(jTable);
        jTable.getSelectionModel().addListSelectionListener(listener);
        jTable.getColumnModel().getSelectionModel().addListSelectionListener(listener);
    }

    public void removeCardSelected() {
        List remove = new ArrayList();
        remove.add((Card) jTable.getModel().getValueAt(
                jTable.getSelectedRow(), 3));
        deck.getCards().removeAll(remove);
    }

    private void loadCardsCantEditor(int limit) {
        //Cant
        final JComboBox cboCant = new JComboBox();
        if (cboCant != null) {
            for (int i = 1; i <= limit; i++) {
                cboCant.addItem(i);
            }
        }
        cboCant.addItemListener(new java.awt.event.ItemListener() {

            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                if (cboCant.getSelectedIndex() < 0) {
                    return;
                }
                if (evt.getStateChange() == ItemEvent.SELECTED) {
                    if (((Card) jTable.getModel().getValueAt(
                            jTable.getSelectedRow(), 3)) == null) {
                        return;
                    }
                    removeCardSelected();
                    for (int i = 0; i < (Integer) evt.getItem(); i++) {
                        deck.getCards().add((Card) jTable.getModel().getValueAt(
                                jTable.getSelectedRow(), 3));
                    }

                    Drecker.inform("Cant. changed to" + deck.getCards().size());
                    updateCardsMetadata();
                }
            }
        });
        DefaultCellEditor dceCant = new DefaultCellEditor(cboCant);
        jTable.getColumnModel().getColumn(6).setCellEditor(dceCant);
    }

    /**
     * Load all the deck's cards into the table rows
     */
    private void loadDeckCardsOnTable() {
        //Clean the table rows
        ((DefaultTableModel) jTable.getModel()).setRowCount(0);
        //Gets the rows information from the deck
        Object[][] newRows = deck.getRows();
        for (int i = 0; i < newRows.length; i++) {
            //load row by row
            Card card = (Card) newRows[i][0];
            ((DefaultTableModel) jTable.getModel()).addRow(new Object[]{
                        card.getExpansion(), card.getPathway(), card.getType().get(0),
                        card, card.getCost(), card.getFrequency(),
                        (Integer) newRows[i][1]
                    });
        }//Update the progress bar
        updateCardsMetadata();
        if (deck.getNotes().compareToIgnoreCase("") != 0) {
            txtaNotes.setText(deck.getNotes());
            txtaNotes.setForeground(Color.black);
        }
    }

    public void updateDeckNotes() {
        if (txtaNotes.getText().compareToIgnoreCase("[Notas]") != 0) {
            deck.setNotes(txtaNotes.getText());
        }
    }

    private void setColumnsWidth() {
        //jTable
        jTable.getColumnModel().getColumn(0).setPreferredWidth(100);
        jTable.getColumnModel().getColumn(0).setMaxWidth(100);
        jTable.getColumnModel().getColumn(1).setPreferredWidth(100);
        jTable.getColumnModel().getColumn(1).setMaxWidth(100);
        jTable.getColumnModel().getColumn(2).setPreferredWidth(100);
        jTable.getColumnModel().getColumn(2).setMaxWidth(100);
        jTable.getColumnModel().getColumn(3).setPreferredWidth(300);
        jTable.getColumnModel().getColumn(4).setPreferredWidth(50);
        jTable.getColumnModel().getColumn(4).setMaxWidth(50);
        jTable.getColumnModel().getColumn(5).setPreferredWidth(100);
        jTable.getColumnModel().getColumn(5).setMaxWidth(100);
        jTable.getColumnModel().getColumn(6).setPreferredWidth(50);
        jTable.getColumnModel().getColumn(6).setMaxWidth(50);
        //loadCombos();

        //jTableCardsCounters
        jTableCardsCounters.setTableHeader(null);
        jTableCardsCounters.getColumnModel().getColumn(1).setPreferredWidth(50);
        jTableCardsCounters.getColumnModel().getColumn(1).setMaxWidth(50);
    }

    public void addNewRow() {
        ((DefaultTableModel) jTable.getModel()).addRow(new Object[7]);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jSplitPaneMain = new javax.swing.JSplitPane();
        jPanelDetails = new javax.swing.JPanel();
        jPanelCards = new javax.swing.JPanel();
        jScrollCardsCounters = new javax.swing.JScrollPane();
        jTableCardsCounters = new javax.swing.JTable();
        pnlCardDetail = new javax.swing.JPanel();
        jSplitPaneDeck = new javax.swing.JSplitPane();
        jScrollPaneNotes = new javax.swing.JScrollPane();
        txtaNotes = new javax.swing.JTextArea();
        jScrollPaneTable = new javax.swing.JScrollPane();
        jTable = new javax.swing.JTable();
        jProgressBar = new javax.swing.JProgressBar();
        btnAddCard = new javax.swing.JButton();
        btnRemoveCard = new javax.swing.JButton();
        lblAlert = new javax.swing.JLabel();

        jSplitPaneMain.setDividerLocation(200);

        jPanelCards.setBorder(javax.swing.BorderFactory.createTitledBorder("Distribución de Cartas:"));

        jTableCardsCounters.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {
                "Title 1", "Title 2"
            }
        ));
        jTableCardsCounters.setToolTipText("Estadísticas Rápidas");
        jTableCardsCounters.setEnabled(false);
        jTableCardsCounters.setFocusable(false);
        jTableCardsCounters.setSelectionMode(javax.swing.ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
        jTableCardsCounters.getTableHeader().setResizingAllowed(false);
        jScrollCardsCounters.setViewportView(jTableCardsCounters);

        pnlCardDetail.setBorder(javax.swing.BorderFactory.createTitledBorder("Carta:"));
        pnlCardDetail.setToolTipText("Detalles de la Carta");
        pnlCardDetail.setMaximumSize(new java.awt.Dimension(250, 32767));
        pnlCardDetail.setPreferredSize(new java.awt.Dimension(250, 201));

        javax.swing.GroupLayout pnlCardDetailLayout = new javax.swing.GroupLayout(pnlCardDetail);
        pnlCardDetail.setLayout(pnlCardDetailLayout);
        pnlCardDetailLayout.setHorizontalGroup(
            pnlCardDetailLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 175, Short.MAX_VALUE)
        );
        pnlCardDetailLayout.setVerticalGroup(
            pnlCardDetailLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 227, Short.MAX_VALUE)
        );

        javax.swing.GroupLayout jPanelCardsLayout = new javax.swing.GroupLayout(jPanelCards);
        jPanelCards.setLayout(jPanelCardsLayout);
        jPanelCardsLayout.setHorizontalGroup(
            jPanelCardsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jScrollCardsCounters, javax.swing.GroupLayout.DEFAULT_SIZE, 188, Short.MAX_VALUE)
            .addComponent(pnlCardDetail, javax.swing.GroupLayout.DEFAULT_SIZE, 187, Short.MAX_VALUE)
        );
        jPanelCardsLayout.setVerticalGroup(
            jPanelCardsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanelCardsLayout.createSequentialGroup()
                .addComponent(jScrollCardsCounters, javax.swing.GroupLayout.DEFAULT_SIZE, 169, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(pnlCardDetail, javax.swing.GroupLayout.PREFERRED_SIZE, 250, javax.swing.GroupLayout.PREFERRED_SIZE))
        );

        javax.swing.GroupLayout jPanelDetailsLayout = new javax.swing.GroupLayout(jPanelDetails);
        jPanelDetails.setLayout(jPanelDetailsLayout);
        jPanelDetailsLayout.setHorizontalGroup(
            jPanelDetailsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jPanelCards, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        jPanelDetailsLayout.setVerticalGroup(
            jPanelDetailsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jPanelCards, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );

        jSplitPaneMain.setLeftComponent(jPanelDetails);

        jSplitPaneDeck.setDividerLocation(320);
        jSplitPaneDeck.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
        jSplitPaneDeck.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
        jSplitPaneDeck.setDoubleBuffered(true);

        txtaNotes.setColumns(20);
        txtaNotes.setForeground(new java.awt.Color(168, 168, 168));
        txtaNotes.setLineWrap(true);
        txtaNotes.setRows(5);
        txtaNotes.setText("[Notas]");
        txtaNotes.setToolTipText("Notas");
        txtaNotes.setWrapStyleWord(true);
        txtaNotes.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusGained(java.awt.event.FocusEvent evt) {
                txtaNotesFocusGained(evt);
            }
            public void focusLost(java.awt.event.FocusEvent evt) {
                txtaNotesFocusLost(evt);
            }
        });
        jScrollPaneNotes.setViewportView(txtaNotes);

        jSplitPaneDeck.setBottomComponent(jScrollPaneNotes);

        jScrollPaneTable.setMinimumSize(new java.awt.Dimension(327, 27));
        jScrollPaneTable.setPreferredSize(new java.awt.Dimension(47, 47));

        jTable.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {null, null, null, null, null, null, null}
            },
            new String [] {
                "Expansion", "Senda", "Tipo", "Carta", "Coste", "Frecuencia", "Cant."
            }
        ) {
            Class[] types = new Class [] {
                java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.Integer.class
            };
            boolean[] canEdit = new boolean [] {
                true, true, true, true, false, false, true
            };

            public Class getColumnClass(int columnIndex) {
                return types [columnIndex];
            }

            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return canEdit [columnIndex];
            }
        });
        jTable.setDragEnabled(true);
        jTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        jScrollPaneTable.setViewportView(jTable);

        jSplitPaneDeck.setTopComponent(jScrollPaneTable);

        jSplitPaneMain.setRightComponent(jSplitPaneDeck);

        jProgressBar.setMaximum(50);
        jProgressBar.setString("0/50");
        jProgressBar.setStringPainted(true);

        btnAddCard.setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/16/add.png"))); // NOI18N
        btnAddCard.setToolTipText("Agregar Carta");
        btnAddCard.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
        btnAddCard.setBorderPainted(false);
        btnAddCard.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnAddCardActionPerformed(evt);
            }
        });

        btnRemoveCard.setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/16/delete.png"))); // NOI18N
        btnRemoveCard.setToolTipText("Quitar Carta");
        btnRemoveCard.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
        btnRemoveCard.setBorderPainted(false);
        btnRemoveCard.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnRemoveCardActionPerformed(evt);
            }
        });

        lblAlert.setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/16/exclamation.png"))); // NOI18N
        lblAlert.setToolTipText("Has superado el limite de cartas permitido!");

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(lblAlert)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jProgressBar, javax.swing.GroupLayout.DEFAULT_SIZE, 771, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(btnAddCard)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(btnRemoveCard))
            .addComponent(jSplitPaneMain, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 847, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addComponent(jSplitPaneMain)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(lblAlert)
                    .addComponent(btnAddCard)
                    .addComponent(btnRemoveCard)
                    .addComponent(jProgressBar, javax.swing.GroupLayout.PREFERRED_SIZE, 17, javax.swing.GroupLayout.PREFERRED_SIZE)))
        );
    }// </editor-fold>//GEN-END:initComponents

private void txtaNotesFocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtaNotesFocusGained
    if (txtaNotes.getText().compareTo("[Notas]") == 0) {
        txtaNotes.setText("");
        txtaNotes.setForeground(Color.black);
    }
}//GEN-LAST:event_txtaNotesFocusGained

private void txtaNotesFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtaNotesFocusLost
    if (txtaNotes.getText().compareToIgnoreCase("") == 0) {
        txtaNotes.setText("[Notas]");
        txtaNotes.setForeground(Color.lightGray);
    }
    updateDeckNotes();
}//GEN-LAST:event_txtaNotesFocusLost

private void btnRemoveCardActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRemoveCardActionPerformed
    if (jTable.getSelectedRow() < 0) {
        return;
    }
    removeCardSelected();
    ((DefaultTableModel) jTable.getModel()).removeRow(jTable.getSelectedRow());
    updateCardsMetadata();
}//GEN-LAST:event_btnRemoveCardActionPerformed

private void btnAddCardActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnAddCardActionPerformed
    ((DefaultTableModel) jTable.getModel()).addRow(new Object[]{});
}//GEN-LAST:event_btnAddCardActionPerformed
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnAddCard;
    private javax.swing.JButton btnRemoveCard;
    private javax.swing.JPanel jPanelCards;
    private javax.swing.JPanel jPanelDetails;
    private javax.swing.JProgressBar jProgressBar;
    private javax.swing.JScrollPane jScrollCardsCounters;
    private javax.swing.JScrollPane jScrollPaneNotes;
    private javax.swing.JScrollPane jScrollPaneTable;
    private javax.swing.JSplitPane jSplitPaneDeck;
    private javax.swing.JSplitPane jSplitPaneMain;
    private javax.swing.JTable jTable;
    private javax.swing.JTable jTableCardsCounters;
    private javax.swing.JLabel lblAlert;
    private javax.swing.JPanel pnlCardDetail;
    private javax.swing.JTextArea txtaNotes;
    // End of variables declaration//GEN-END:variables

    private void prepareRenders() {
        jTable.setModel(new CustomTableModel());

        //Expansion
        final JComboBox cboExpansion = new JComboBox();
        List lstExpansion = Queries.getExpansions();
        if (cboExpansion != null) {
            cboExpansion.removeAllItems();
            for (int i = 0; lstExpansion.size() > i; i++) {
                cboExpansion.addItem(lstExpansion.get(i));
            }
        }
        cboExpansion.addItemListener(new java.awt.event.ItemListener() {

            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                if (cboExpansion.getSelectedIndex() < 0) {
                    return;
                }
                if (evt.getStateChange() == ItemEvent.SELECTED) {
                    loadCards((Expansion) evt.getItem(),
                            (Pathway) jTable.getModel().getValueAt(
                            jTable.getSelectedRow(), 1),
                            (Type) jTable.getModel().getValueAt(
                            jTable.getSelectedRow(), 2));
                }
            }
        });
        DefaultCellEditor dceExpansion = new DefaultCellEditor(cboExpansion);
        jTable.getColumnModel().getColumn(0).setCellEditor(dceExpansion);

        //Pathway
        final JComboBox cboPathway = new JComboBox();
        /*List lstPathways = Queries.getPathways();
        if (cboPathway != null) {
        cboPathway.removeAllItems();
        for (int i = 0; lstPathways.size() > i; i++) {
        cboPathway.addItem(lstPathways.get(i));
        }
        }*/
        cboPathway.addItem(deck.getDemon().getPathway());
        cboPathway.addItem(Queries.getPathway("Neutral"));
        cboPathway.addItemListener(new java.awt.event.ItemListener() {

            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                if (cboPathway.getSelectedIndex() < 0) {
                    return;
                }
                if (evt.getStateChange() == ItemEvent.SELECTED) {
                    loadCards((Expansion) jTable.getModel().getValueAt(
                            jTable.getSelectedRow(), 0),
                            (Pathway) evt.getItem(),
                            (Type) jTable.getModel().getValueAt(
                            jTable.getSelectedRow(), 2));
                }
            }
        });
        DefaultCellEditor dcePathway = new DefaultCellEditor(cboPathway);
        jTable.getColumnModel().getColumn(1).setCellEditor(dcePathway);

        //Type
        final JComboBox cboTypes = new JComboBox();
        List lstTypes = Queries.getTypes();
        if (cboTypes != null) {
            cboTypes.removeAllItems();
            for (int i = 0; lstTypes.size() > i; i++) {
                cboTypes.addItem(lstTypes.get(i));
            }
        }
        cboTypes.addItemListener(new java.awt.event.ItemListener() {

            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                if (cboTypes.getSelectedIndex() < 0) {
                    return;
                }
                if (evt.getStateChange() == ItemEvent.SELECTED) {
                    loadCards((Expansion) jTable.getModel().getValueAt(
                            jTable.getSelectedRow(), 0),
                            (Pathway) jTable.getModel().getValueAt(
                            jTable.getSelectedRow(), 1),
                            (Type) evt.getItem());
                }
            }
        });
        DefaultCellEditor dceTypes = new DefaultCellEditor(cboTypes);
        jTable.getColumnModel().getColumn(2).setCellEditor(dceTypes);

        loadCardsCantEditor(4);

    }

    /**
     * @return the deck
     */
    public Deck getDeck() {
        return deck;
    }

    /**
     * @param deck the deck to set
     */
    public void setDeck(Deck deck) {
        this.deck = deck;
    }

    /**
     * @return the deck metadata
     */
    public DeckMetadata getDeckMetadata() {
        return metadata;
    }

    /***
     * Recives the expansion, the pathway and the type of the cards to load
     * from the DB into the 'Cards' column.
     * Creates and set a new jComboBox (with the list of the cards) as cell
     * editor, and add a itemStateChange listener that reacts when a new card
     * is selected
     * @param expansion
     * @param pathway
     * @param type 
     */
    private void loadCards(Expansion expansion, Pathway pathway, Type type) {
        List lstCards = Queries.getCards(expansion, pathway, type);//gets the cards
        Drecker.inform(lstCards.size() + " cards to been shown.");

        //Creates the new combo box with the cards form the query
        final JComboBox cboCards = new JComboBox();
        if (cboCards != null) {
            cboCards.removeAllItems();
            for (int i = 0; lstCards.size() > i; i++) {
                cboCards.addItem(lstCards.get(i));
            }
        }
        cboCards.addItemListener(new java.awt.event.ItemListener() {
            //add the listener.

            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                if (cboCards.getSelectedIndex() < 0) {
                    return;//If there is no card selected, just return.
                }
                if (evt.getStateChange() == ItemEvent.SELECTED) {//Verifies wich action was made.
                    Card card = (Card) evt.getItem();//Sets the Cost and Frequency in ther respective columns
                    jTable.getModel().setValueAt(card.getExpansion(), jTable.getSelectedRow(), 0);
                    jTable.getModel().setValueAt(card.getPathway(), jTable.getSelectedRow(), 1);
                    jTable.getModel().setValueAt(card.getType().get(0), jTable.getSelectedRow(), 2);
                    jTable.getModel().setValueAt(card.getCost(), jTable.getSelectedRow(), 4);
                    jTable.getModel().setValueAt(card.getFrequency(), jTable.getSelectedRow(), 5);
                    //Print the selected card information
                    Drecker.inform("Card Change: " + (Card) jTable.getModel().getValueAt(
                            jTable.getSelectedRow(), 3) + " for " + card);

                    boolean isUnlimited = ((Card) evt.getItem()).getSupertype().toString().contains(unlimit.toString());

                    //If there are no cant selected, the methods return here
                    if (((Integer) jTable.getModel().getValueAt(
                            jTable.getSelectedRow(), 6)) == null) {
                        //If the selected card is unlimited supertyped, set the max val of the cant allowded to 50
                        if (isUnlimited) {
                            loadCardsCantEditor(50);
                        } else {
                            loadCardsCantEditor(4);
                        }
                        return;
                    }
                    //If there was a card selected before, it removes it from the deck
                    if (((Card) jTable.getModel().getValueAt(
                            jTable.getSelectedRow(), 3)) != null) {
                        removeCardSelected();
                    }

                    //saves the cant of the selected card
                    int cant = (Integer) jTable.getModel().getValueAt(
                            jTable.getSelectedRow(), 6);
                    if (cant > 4 && !isUnlimited) {
                        cant = 4;//If the card is not unlimited, and there was a cant bigger than 4, then sets the cant to 4.
                    }
                    if (isUnlimited) {
                        loadCardsCantEditor(50);
                    } else {
                        loadCardsCantEditor(4);
                    }
                    jTable.getModel().setValueAt(cant, jTable.getSelectedRow(), 6);

                    //And finally, add the new card selected
                    for (int i = 0; i < cant; i++) {
                        deck.getCards().add((Card) evt.getItem());
                    }

                    Drecker.inform("Deck Cards(" + deck.getCards().size() + ")");
                    updateCardsMetadata();
                }
            }
        });
        DefaultCellEditor dceCards = new DefaultCellEditor(cboCards);
        //DefaultCellEditor dceCards = (DefaultCellEditor)jTable.getCellEditor(jTable.getSelectedRow(), 3);
        //JComboBox a = (JComboBox)dceCards.getComponent();
        jTable.getColumnModel().getColumn(3).setCellEditor(dceCards);
    }

    private void updateCardsMetadata() {
        //Frequencies
        HashMap<String, Integer> frequencies = initateHashMap(Queries.getFrequencies());
        //Pathways
        HashMap<String, Integer> pathways = initateHashMap(Queries.getPathways());
        //types
        HashMap<String, Integer> types = initateHashMap(Queries.getTypes());
        //Supertypes
        HashMap<String, HashMap<String, Integer>> supertypes = initateNestedHashMap(
                Queries.getTypes(), Queries.getSupertypes());
        //cost
        int[] cost = new int[15];

        for (Object card : deck.getCards().toArray()) {
            //Frequencies
            String freq = ((Card) card).getFrequency().getName();
            frequencies.put(freq, frequencies.get(freq) + 1);

            //Pathways
            String pathw = ((Card) card).getPathway().getName();
            pathways.put(pathw, pathways.get(pathw) + 1);

            //types
            for (Object type : ((Card) card).getType()) {
                String tpe = ((Type) type).getName();
                types.put(tpe, types.get(tpe) + 1);
                for (Object suptype : ((Card) card).getSupertype()) {
                    String suptpe = ((Supertype) suptype).getName();
                    HashMap<String, Integer> hmSupType = supertypes.get(tpe);
                    hmSupType.put(suptpe, hmSupType.get(suptpe) + 1);
                    hmSupType.put(tpe, hmSupType.get(tpe) + 1);
                }
            }

            //cost
            try {
                cost[Integer.parseInt(((Card) card).getCost())]++;
            } catch (IndexOutOfBoundsException e) {
            } catch (NumberFormatException e) {
                //Here counts the cards with X cost
                cost[0]++;
            }
        }

        //Completing the SuperTypes MetaData
        for (Iterator it = supertypes.entrySet().iterator(); it.hasNext();) {
            Map.Entry e = (Map.Entry) it.next();
            HashMap<String, Integer> subtype = ((HashMap<String, Integer>)  e.getValue());
            subtype.put((String)e.getKey(),types.get(e.getKey())-subtype.get(e.getKey()));
        }

        //Saves the stadistics on the Deck's Metadata
        metadata.setSupertypes(supertypes);
        metadata.setTypes(types);
        metadata.setCost(cost);

        jProgressBar.setValue(deck.getCards().size());
        jProgressBar.setString(deck.getCards().size() + "/50");
        lblAlert.setVisible(deck.getCards().size() > 50);
        if (deck.getCards().size() > 50) {
            JOptionPane.showMessageDialog(this,
                    "Has excedido el límite máximo de cartas permitidas en el mazo.",
                    "Límite Excedido", JOptionPane.INFORMATION_MESSAGE);
        }
        DefaultTableModel tModel = (DefaultTableModel) jTableCardsCounters.getModel();
        tModel.setRowCount(0);

        //Frequencies
        tModel.addRow(new Object[]{"FRECUENCIAS", ""});
        fillTableModel(frequencies, tModel);

        //Pathways
        tModel.addRow(new Object[]{"SENDAS", ""});
        fillTableModel(pathways, tModel);

        //Types
        tModel.addRow(new Object[]{"TIPOS", ""});
        fillTableModel(types, tModel);

        DefaultListSelectionModel dlsm = new DefaultListSelectionModel();
        dlsm.addSelectionInterval(0, 0);
        dlsm.addSelectionInterval(5, 5);
        dlsm.addSelectionInterval(11, 11);

        jTableCardsCounters.setSelectionModel(dlsm);

    }

    public class SelectionListener implements ListSelectionListener {

        JTable table;

        // It is necessary to keep the table since it is not possible
        // to determine the table from the event's source
        SelectionListener(JTable table) {
            this.table = table;
        }

        public void valueChanged(ListSelectionEvent e) {
            //Must be a row selected. This could happend on deleiitng rows.
            if (table.getSelectedRow() == -1) {
                return;
            }
            // If cell selection is enabled, both row and column change events are fired
            if (e.getSource() == table.getSelectionModel()
                    && table.getRowSelectionAllowed()) {
                // Column selection changed
                Drecker.inform("Changing column combo");
                loadCards((Expansion) table.getModel().getValueAt(
                        table.getSelectedRow(), 0),
                        (Pathway) table.getModel().getValueAt(
                        table.getSelectedRow(), 1),
                        (Type) table.getModel().getValueAt(
                        table.getSelectedRow(), 2));
            } else if (e.getSource() == table.getColumnModel().getSelectionModel()
                    && table.getColumnSelectionAllowed()) {
                // Row selection changed
                int first = e.getFirstIndex();
                Drecker.inform("Changing column combo");
                loadCards((Expansion) table.getModel().getValueAt(
                        first, 0),
                        (Pathway) table.getModel().getValueAt(
                        first, 1),
                        (Type) table.getModel().getValueAt(
                        first, 2));
            }

            if (e.getValueIsAdjusting()) {
                // The mouse button has not yet been released
            }
        }
    }

    /**
     * Initiate a HashMap using the toString of the elements of the list
     * as HashKey, and a '0' as initial value.
     * @param list List of the HashKey of the Elements
     * @return a HashMap with the elements toString as Key and '0' in each
     * value
     */
    private HashMap<String, Integer> initateHashMap(List list) {
        HashMap hashmap = new HashMap<String, Integer>();
        for (Object row : list) {
            hashmap.put(row.toString(), 0);
        }
        return hashmap;
    }

    /**
     * Initiate a HashMap using the toString of the elements of the first list
     * as HashKey, and a HashMap, with the elements of the second list
     * as Key, as initial value.
     * @param fList List of the HashKey of the Elements
     * @param sList List of the HashKey of the HashMap in each value of the principal
     * @return a HashMap with the elements toString as Key and a nested HashMap
     * as value
     */
    private HashMap<String, HashMap<String, Integer>> initateNestedHashMap(List fList, List sList) {
        HashMap<String, HashMap<String, Integer>> hashmap =
                new HashMap<String, HashMap<String, Integer>>();
        for (Object row : fList) {
            hashmap.put(row.toString(), initateHashMap(sList));
            hashmap.get(row.toString()).put(row.toString(), 0);
        }
        return hashmap;
    }

    private void fillTableModel(HashMap source, DefaultTableModel tModel) {
        for (Iterator it = source.entrySet().iterator(); it.hasNext();) {
            Map.Entry e = (Map.Entry) it.next();
            tModel.addRow(new Object[]{e.getKey(), e.getValue()});
        }
    }
}
